﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using HalconDotNet;
using System.IO;
using MathNet.Numerics.Statistics;

namespace V3301VisionLibrary_NS
{
    namespace Measure_NS
    {
        public class MeasureConfig
        {
            /// <summary>
            /// "first","last","all",
            /// </summary>
            public string select = "first";
            /// <summary>
            ///"all""all_strongest""negative""negative_strongest""positive""positive_strongest"
            /// </summary>
            public string translation = "negative";
            /// <summary>
            /// 根据测量两条线的平行长度设置，不能设置过大，会导致没有测量结果,默认值为5
            /// </summary>
            public double measureLength2 = 5.0d;
            public double sigma = 3.0d;
            public double threshold = 10;
            public ROIRectangle2 roi = new ROIRectangle2();
            public int singleMeasureTimes = 10;
            /// <summary>
            /// 设置滤波系数，值越大滤波强度越大，保留的数据越少
            /// </summary>
            public double fileterRate = 2;
        }
        public class ROIRectangle2
        {
            public double row;
            public double col;
            public double phi;
            public double length1;
            public double length2;
        }
        public class Measure
        {
            /// <summary>
            /// 如果需要显示间隙位置，请设置window,不需要显示设置为null
            /// </summary>
            public HWindow hwindow
            {
                get { return _hwindow; }
                set
                {
                    _hwindow = value;
                    _hwindow.SetDraw("fill");
                }
            }
            private HWindow _hwindow { get; set; } = null;
            public MeasureConfig config = new MeasureConfig();
            public double widthLimitDefault
            {
                get { return _widthLimitDefault; }
                set
                {
                    if (value > 0)
                    {
                        _widthLimitDefault = value;
                    }
                }
            }
            private double _widthLimitDefault { get; set; } = 5;
            public void Init(MeasureConfig config)
            {
                this.config = config;
            }
            /// <summary>
            /// 用于单个间隙的测量，做singleMeasureTimes（奇数）次平均，调用前赋值ROI
            /// </summary>
            /// <param name="srcImage"></param>
            /// <param name="select"(只能选择first或者last,否则会出错)></param>
            /// <param name="transition"></param>
            /// <param name="distance"></param>
            /// <param name="sigma"></param>
            /// <param name="threshold"></param>
            public bool MeasureSingleDistance(HImage srcImage, out double distance)
            {
                distance = -1;
                int width, height;
                double measureRow, measureCol, measurePhi, measureLen1, measureLen2;
                try
                {
                    srcImage.GetImageSize(out width, out height);
                    HMeasure hmeasure = new HMeasure();
                    double perLen = config.roi.length2 * 2 / config.singleMeasureTimes;
                    HTuple firstEdgesRow, secondEdgesRow, firstEdgesCol, secondEdgesCol, firstAmp, secondAmp;
                    HTuple distanceIntra, distanceInter;
                    double[] result = new double[config.singleMeasureTimes];
                    measurePhi = config.roi.phi;
                    if (config.measureLength2 > config.roi.length2 || config.measureLength2 <= 0)
                    {
                        measureLen2 = _widthLimitDefault;
                    }
                    else
                    {
                        measureLen2 = config.measureLength2;
                    }
                    measureLen1 = config.roi.length1;
                    for (int i = 0; i < config.singleMeasureTimes; i++)
                    {
                        measureRow = config.roi.row + (i - config.singleMeasureTimes / 2) * perLen * Math.Cos(config.roi.phi);
                        measureCol = config.roi.col + (i - config.singleMeasureTimes / 2) * perLen * Math.Sin(config.roi.phi);
                        hmeasure.GenMeasureRectangle2(measureRow, measureCol, measurePhi, measureLen1, measureLen2, width, height, "nearest_neighbor");
                        hmeasure.MeasurePairs(srcImage, config.sigma, config.threshold, config.translation, config.select,
                        out firstEdgesRow, out firstEdgesCol, out firstAmp, out secondEdgesRow, out secondEdgesCol, out secondAmp
                        , out distanceIntra, out distanceInter);
                        result[i] = firstEdgesCol.Length == 1 ? distanceIntra.D : 0;
                        if (_hwindow != null)
                        {
                            _hwindow.DispCross(firstEdgesRow, firstEdgesCol, 6, config.roi.phi);
                            _hwindow.DispCross(secondEdgesRow, secondEdgesCol, 6, config.roi.phi);
                        }
                    }
                    double[] resultFilter;
                    Filter(result, out resultFilter);
                    distance = resultFilter.Average();
                    return true;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    return false;
                }
            }
            public bool MeasureMutilDistance(HImage srcImage, out double[] distanceIntra, out double[] distanceInter)
            {
                distanceInter = null;
                distanceIntra = null;
                try
                {
                    distanceInter = null;
                    distanceIntra = null;
                    int width, height;
                    double measureLen2;
                    if (config.measureLength2 <= 0 || config.measureLength2 > config.roi.length2)
                    {
                        measureLen2 = _widthLimitDefault;
                    }
                    else
                    {
                        measureLen2 = config.measureLength2;
                    }
                    srcImage.GetImageSize(out width, out height);
                    HMeasure hmeasure = new HMeasure(config.roi.row, config.roi.col, config.roi.phi, config.roi.length1,
                        measureLen2, width, height, "nearest_neighbor");
                    HTuple firstEdgesRow, secondEdgesRow, firstEdgesCol, secondEdgesCol, firstAmp, secondAmp;
                    HTuple Intra, Inter;
                    hmeasure.MeasurePairs(srcImage, config.sigma, config.threshold, config.translation, config.select,
                        out firstEdgesRow, out firstEdgesCol, out firstAmp, out secondEdgesRow, out secondEdgesCol,
                        out secondAmp, out Intra, out Inter);
                    distanceInter = Inter;
                    distanceIntra = Intra;
                    if (_hwindow != null)
                    {
                        _hwindow.DispCross(firstEdgesRow, firstEdgesCol, 6, config.roi.phi);
                        _hwindow.DispCross(secondEdgesRow, secondEdgesCol, 6, config.roi.phi);
                    }
                    return true;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    return false;
                }
            }
            /// <summary>
            /// 求均方差
            /// </summary>
            /// <param name="inData"></param>
            /// <returns></returns>
            private double CalculateStdDev(double[] inData)
            {
                double ret = 0;
                var data = inData.ToList();
                if (data.Count > 0)
                {
                    double avg = data.Average();
                    double sum = inData.Sum(d => Math.Pow(d - avg, 2));
                    ret = Math.Sqrt(sum / inData.Length);
                }
                return ret;
            }
            /// <summary>
            /// singleMeasureTimes倍均方差滤波,默认值为2
            /// </summary>
            /// <param name="value"></param>
            /// <param name="result"></param>
            private void Filter(double[] value, out double[] result)
            {
                try
                {
                    var valueList = value.ToList();
                    result = value;
                    if (value.Length <= 0)
                    {
                        return;
                    }
                    var StdDev = CalculateStdDev(value);
                    valueList.Sort();
                    var mid = valueList[valueList.Count / 2];
                    for (int i = 0; i < valueList.Count; i++)
                    {
                        if (Math.Abs(mid - valueList[i]) > config.fileterRate * StdDev)
                        {
                            valueList.RemoveAt(i);
                            i--;
                        }
                    }
                    result = valueList.ToArray();
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    throw e;
                }
            }
        }
    }
    namespace HoleCheck_NS
    {
        public class HoleCheckConfig
        {
            public ROI_HoleCheck roi;
            public int meanImageWidth = 300;
            public int meanImageHeight = 300;
            public double dynThresholdOffset = 2;
            public string dynDarkOrLight = "dark";
            public double selectShapeAreaMin = 0;
            public double selectShapeAreaMax = 10000;
            public double fillupMin = 1;
            public double fillupMax = 500;
            public double closingCircleRadius = 9;
            public double openingCircleRadius = 21;
        }
        public class ROI_HoleCheck
        {
            public double row;
            public double col;
            public double phi;
            public double len1;
            public double len2;
        }
        public class HoleCheck
        {
            public HoleCheckConfig config = new HoleCheckConfig();
            public HWindow hwindow = null;
            public void Init(HoleCheckConfig config)
            {
                this.config = config;
            }
            public bool Check(HImage image, out int count, out double diffArea)
            {
                count = 0;
                diffArea = 0;
                try
                {
                    HRegion rectangle2 = new HRegion();
                    rectangle2.GenRectangle2(config.roi.row, config.roi.col, config.roi.phi, config.roi.len1, config.roi.len2);
                    var imageReduce = image.ReduceDomain(rectangle2);
                    var imageMean = imageReduce.MeanImage(config.meanImageWidth, config.meanImageHeight);
                    var region = imageReduce.DynThreshold(imageMean, config.dynThresholdOffset, config.dynDarkOrLight);
                    var regionConnection = region.Connection();
                    var regionSelect = regionConnection.SelectShape("area", "and", config.selectShapeAreaMin, config.selectShapeAreaMax);
                    var regionFillUp = regionSelect.FillUpShape("area", config.fillupMin, config.fillupMax);
                    var regionClosing = regionFillUp.ClosingCircle(config.closingCircleRadius);
                    var regionopening = regionClosing.OpeningCircle(config.openingCircleRadius);
                    var regionDiff = regionClosing.Difference(regionopening);
                    var regiondiffconnection = regionDiff.Connection();
                    if (regiondiffconnection.CountObj() > 0)
                    {
                        var area = regiondiffconnection.Area;
                        diffArea = area.TupleMax().D;
                        if (hwindow != null)
                        {
                            hwindow.SetColor("red");
                            hwindow.DispRegion(regiondiffconnection);
                        }
                    }
                    count = regionSelect.CountObj();
                    return true;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    return false;
                }
            }
        }
    }
    namespace FindCircle_NS
    {
        public class Circle
        {
            public double Row;
            public double Col;
            public double Radius;
        }
        public class FindCircleConfig
        {
            public Circle circleSmall1 = new Circle();
            public Circle circleBig1 = new Circle();
            public Circle circleSmall2 = new Circle();
            public Circle circleBig2 = new Circle();
            public double EdgesSubPix_Alpha = 5;
            public double EdgesSubPix_Low = 10;
            public double EdgesSubPix_High = 30;
            public double circularityMin = 0.4;
            public double circularityMax = 1.0;
            public double contLengthMin = 100;
            public double contLengthMax = 100000;
        }
        public class FindCircle
        {
            public FindCircleConfig config = new FindCircleConfig();
            public HWindow hwindow = null;
            public void Init(FindCircleConfig config)
            {
                this.config = config;
            }
            public bool FindSingleCircle(HImage image, int c1Orc2, out Circle circle)
            {
                circle = new Circle();
                try
                {
                    HXLDCont xld = new HXLDCont();
                    HTuple row, col, startphi, endphi, radius;
                    HTuple o;
                    HRegion c1 = new HRegion();
                    HRegion c2 = new HRegion();
                    Circle csmall, cbig;
                    if (c1Orc2 == 1)
                    {
                        csmall = config.circleSmall1;
                        cbig = config.circleBig1;
                    }
                    else
                    {
                        csmall = config.circleSmall2;
                        cbig = config.circleBig2;
                    }
                    c1.GenCircle(csmall.Row, csmall.Col, csmall.Radius);
                    c2.GenCircle(cbig.Row, cbig.Col, cbig.Radius);
                    HRegion cregion = c2.Difference(c1);
                    HImage imagereduce = image.ReduceDomain(cregion);
                    xld = imagereduce.EdgesSubPix("canny", config.EdgesSubPix_Alpha, config.EdgesSubPix_Low, config.EdgesSubPix_High);
                    xld = xld.SelectShapeXld("circularity", "and", config.circularityMin, config.circularityMax);
                    xld = xld.SelectShapeXld("contlength", "and", config.contLengthMin, config.contLengthMax);
                    if (xld.CountObj() < 1)
                    {
                        return false;
                    }
                    else
                    {
                        List<double> circularitys = xld.CircularityXld().DArr.ToList();
                        int index = circularitys.FindIndex(d =>
                        {
                            if (d >= circularitys.Max())
                            {
                                return true;
                            }
                            else return false;
                        });
                        HXLDCont x = xld.SelectObj(index + 1);
                        x.FitCircleContourXld("algebraic", -1, 0, 0, 3, 2, out row, out col, out radius, out startphi, out endphi, out o);
                        HRegion c = new HRegion();
                        c.GenCircle(row, col, radius);
                        if (hwindow != null)
                        {
                            hwindow.SetDraw("margin");
                            hwindow.SetColor("blue");
                            hwindow.DispRegion(c);
                        }
                        circle.Row = row;
                        circle.Col = col;
                        circle.Radius = radius;
                        return true;
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    return false;
                }
            }
            public bool FindTwoCircle(HImage image, out int numberCircle, out Circle circle1, out Circle circle2)
            {
                circle1 = new Circle();
                circle2 = new Circle();
                numberCircle = 0;
                try
                {
                    HXLDCont xld = new HXLDCont();
                    HTuple row, col, startphi, endphi, radius;
                    HTuple o;
                    HRegion c1 = new HRegion();
                    HRegion c2 = new HRegion();
                    Circle csmall = config.circleSmall1;
                    Circle cbig = config.circleBig1;
                    c1.GenCircle(csmall.Row, csmall.Col, csmall.Radius);
                    c2.GenCircle(cbig.Row, cbig.Col, cbig.Radius);
                    HRegion cregion = c2.Difference(c1);
                    HImage imagereduce = image.ReduceDomain(cregion);
                    xld = imagereduce.EdgesSubPix("canny", config.EdgesSubPix_Alpha, config.EdgesSubPix_Low, config.EdgesSubPix_High);
                    xld = xld.SelectShapeXld("circularity", "and", config.circularityMin, config.circularityMax);
                    xld = xld.SelectShapeXld("contlength", "and", config.contLengthMin, config.contLengthMax);
                    numberCircle = xld.CountObj();
                    if (numberCircle >= 2)
                    {
                        List<double> circularitys = xld.CircularityXld().DArr.ToList();
                        double[] circularityscopy = new double[numberCircle];
                        circularitys.CopyTo(circularityscopy);
                        for (int i = 0; i < 2; i++)
                        {

                            int index = circularityscopy.ToList().FindIndex(d =>
                            {
                                if (d == circularitys.Max())
                                {
                                    return true;
                                }
                                else return false;
                            });
                            HXLDCont x = xld.SelectObj(index + 1);
                            if (i == 0) circularitys.RemoveAt(index);
                            x.FitCircleContourXld("algebraic", -1, 0, 0, 3, 2, out row, out col, out radius, out startphi, out endphi, out o);
                            HRegion circle = new HRegion();
                            circle.GenCircle(row, col, radius);
                            if (hwindow != null)
                            {
                                hwindow.SetDraw("margin");
                                hwindow.SetColor("blue");
                                hwindow.DispRegion(circle);
                            }
                            if (i == 0)
                            {
                                circle1.Row = row;
                                circle1.Col = col;
                                circle1.Radius = radius;
                            }
                            else
                            {
                                circle2.Row = row;
                                circle2.Col = col;
                                circle2.Radius = radius;
                            }
                        }
                    }
                    else if (numberCircle == 1)
                    {
                        List<double> circularitys = xld.CircularityXld().DArr.ToList();
                        int index = circularitys.FindIndex(d =>
                        {
                            if (d >= circularitys.Max())
                            {
                                return true;
                            }
                            else return false;
                        });
                        HXLDCont x = xld.SelectObj(index + 1);
                        circularitys.RemoveAt(index);
                        x.FitCircleContourXld("algebraic", -1, 0, 0, 3, 2, out row, out col, out radius, out startphi, out endphi, out o);
                        HRegion circle = new HRegion();
                        circle.GenCircle(row, col, radius);
                        if (hwindow != null)
                        {
                            hwindow.SetDraw("margin");
                            hwindow.SetColor("blue");
                            hwindow.DispRegion(circle);
                        }

                        circle1.Row = row;
                        circle1.Col = col;
                        circle1.Radius = radius;
                    }
                    return true;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    return false;
                }
            }
            public bool GetDistance2Circle_1Circle(HImage image, out double distance)
            {
                distance = 0;
                try
                {
                    int number;
                    Circle circle1, circle2;
                    if (FindTwoCircle(image, out number, out circle1, out circle2))
                    {
                        if (number >= 2)
                        {
                            distance = HMisc.DistancePp(circle1.Row, circle1.Col, circle2.Row, circle2.Col);
                            return true;
                        }
                        else
                        {
                            return false;
                        }
                    }
                    else return false;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    return false;
                }
            }
            public bool GetDistance2Circle_2Circle(HImage image, out double distance)
            {
                distance = 0;
                try
                {
                    Circle circle1, circle2;
                    if (!FindSingleCircle(image, 1, out circle1))
                    {
                        return false;
                    }
                    if (!FindSingleCircle(image, 2, out circle2))
                    {
                        return false;
                    }
                    distance = HMisc.DistancePp(circle1.Row, circle1.Col, circle2.Row, circle2.Col);
                    return true;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    return false;
                }
            }
        }
    }
    namespace LogoMatch_NS
    {
        public class LogoMatchConfig
        {
            public double PrepareVarAbsThreshold = 50;
            public double PrepareVarVarThreshold = 5;
            public double SelectShapeAreaMin = 50;
            public double SelectShapeAreaMax = 100000;
            public double FindShapeModelAngleMin = 0;
            public double FindShapeModelAngleMax = 360;
            public double FindShapeModelScore = 0.5;
            public string PathShapeModel = "";
            public string PathVarModel = "";
            public string PathShapeModelImage = "";
        }
        public class LogoMatch
        {
            public LogoMatchConfig config = new LogoMatchConfig();
            public HWindow hwindow = null;
            private HShapeModel hShapeModel = new HShapeModel();
            private HVariationModel hVarModel = new HVariationModel();
            private HImage hRefImage = new HImage();
            private HRegion hModelRegion = new HRegion();
            private HRegion hModelRegion1 = new HRegion();
            private HTuple fModelRow = 0;
            private HTuple fModelCol = 0;
            private int nWidth = 0;
            private int nHeight = 0;
            /// <summary>
            /// 调用此初始化前，必须对调用对象的config赋值，否则会出错
            /// </summary>
            /// <returns></returns>
            private bool Init()
            {
                try
                {
                    hShapeModel.ReadShapeModel(config.PathShapeModel);
                    hVarModel.ReadVariationModel(config.PathVarModel);
                    hRefImage.ReadImage(config.PathShapeModelImage);
                    hModelRegion = hRefImage.GetDomain();
                    hModelRegion.AreaCenter(out fModelRow, out fModelCol);
                    hRefImage.GetImageSize(out nWidth, out nHeight);
                    hRefImage.InspectShapeModel(out hModelRegion1, 1, 30);
                    hVarModel.PrepareVariationModel(config.PrepareVarAbsThreshold, config.PrepareVarVarThreshold);
                    return true;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    return false;
                }
            }
            public bool Init(LogoMatchConfig config)
            {
                this.config = config;
                if (!Init())
                {
                    return false;
                }
                return true;
            }
            public bool Match(HImage image, out double area)
            {
                area = 0;
                try
                {
                    HImage imageGray = new HImage();
                    imageGray = image.Rgb1ToGray();
                    HTuple row, col, angle, score, model;
                    hShapeModel.FindShapeModels(imageGray, config.FindShapeModelAngleMin / 3.1415926, config.FindShapeModelAngleMax / 3.1415926
                        , config.FindShapeModelScore, 1, 0.5, "least_squares", 0, 0.9, out row, out col, out angle, out score,
                        out model);
                    if (score.TupleLength() == 1)
                    {
                        HHomMat2D hmat = new HHomMat2D();
                        hmat.VectorAngleToRigid(row, col, angle, fModelRow, fModelCol, 0);
                        var imageTrans = hmat.AffineTransImageSize(imageGray, "constant", nWidth, nHeight);
                        var regionDiff = hVarModel.CompareVariationModel(imageTrans);
                        regionDiff = regionDiff.OpeningRectangle1(3, 3);
                        var regionConnection = regionDiff.Connection();
                        var regionSelect = regionConnection.SelectShape("area", "and", config.SelectShapeAreaMin, config.SelectShapeAreaMax);
                        var count = regionSelect.CountObj();
                        hmat.VectorAngleToRigid(fModelRow, fModelCol, 0, row, col, angle);
                        if (hwindow != null)
                        {
                            var regionModel = hmat.AffineTransRegion(hModelRegion1, "nearest_neighbor");
                            hwindow.SetColor("blue");
                            hwindow.SetDraw("margin");
                            hwindow.DispRegion(regionModel);
                        }
                        if (count > 0)
                        {
                            if (hwindow != null)
                            {
                                var regionErr = hmat.AffineTransRegion(regionSelect, "nearest_neighbor");
                                hwindow.SetColor("red");
                                hwindow.DispRegion(regionErr);
                            }
                            area = regionSelect.Area.TupleMax().D;
                        }
                    }
                    return true;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    return false;
                }
            }
        }

    }
    namespace ZoomWindow_NS
    {
        public class ZoomWindow
        {
            public HImage image
            {
                get { return _image; }
                set
                {
                    _image = value; if (_hWindowControl != null)
                    {
                        try
                        {
                            _hWindowControl.HalconWindow.DispImage(_image);
                        }
                        catch (Exception e)
                        {
                            Console.WriteLine(e.ToString());
                        }
                    }
                }
            }
            private HImage _image { get; set; }
            public HWindowControl hWindowControl
            {
                get { return _hWindowControl; }
                set
                {
                    _hWindowControl = value;
                    if (value != null)
                    {
                        EnableZoom();
                    }
                }
            }
            private HWindowControl _hWindowControl { get; set; } = null;
            private bool bMouseDown = false;
            private bool bMouseMoved = false;
            private int nMouseDownR;
            private int nMouseDownC;
            private int nMouseMoveEndR;
            private int nMouseMoveEndC;
            private DateTime time1 = DateTime.Now;
            private HWindow hwindow { get { return _hWindowControl == null ? null : _hWindowControl.HalconWindow; } }
            /// <summary>
            /// 使用前请为成员变量image/hWindowControl赋值
            /// </summary>
            public ZoomWindow()
            { }
            /// <summary>
            /// 使用前请为成员变量image/hWindowControl赋值
            /// </summary>
            /// <param name="window"></param>
            public ZoomWindow(HWindowControl window)
            {
                hWindowControl = window;
                EnableZoom();
            }
            private void hWindowControl_HMouseWheel(object sender, HMouseEventArgs e)
            {
                try
                {
                    double row = 0, col = 0;
                    int but;
                    hwindow.GetMpositionSubPix(out row, out col, out but);
                    int partR1, partC1, partR2, partC2;
                    hwindow.GetPart(out partR1, out partC1, out partR2, out partC2);
                    if (e.Delta < 0)//缩小
                    {
                        partR1 = partR1 - (int)(0.5 * Math.Abs(partR1 - row));
                        partC1 = partC1 - (int)(0.5 * Math.Abs(partC1 - col));
                        partR2 = partR2 + (int)(Math.Abs(partR2 - row) * 0.5);
                        partC2 = partC2 + (int)(Math.Abs(partC2 - col) * 0.5);
                    }
                    else if (e.Delta > 0)//放大
                    {
                        partR1 = partR1 + (int)(0.5 * Math.Abs(partR1 - row));
                        partC1 = partC1 + (int)(0.5 * Math.Abs(partC1 - col));
                        partR2 = partR2 - (int)(Math.Abs(partR2 - row) * 0.5);
                        partC2 = partC2 - (int)(Math.Abs(partC2 - col) * 0.5);
                    }
                    hwindow.ClearWindow();
                    hwindow.SetPart(partR1 < -10000 ? -10000 : partR1, partC1 < -10000 ? -10000 : partC1,
                        partR2 > 10000 ? 10000 : partR2, partC2 > 10000 ? 10000 : partC2);
                    image.DispImage(hwindow);
                }
                catch (Exception exception)
                {
                    //throw exception;
                    Console.WriteLine(exception.ToString());
                }
            }
            private void hWindowControl_HMouseDown(object sender, HMouseEventArgs e)
            {
                try
                {
                    if (e.Button == System.Windows.Forms.MouseButtons.Left)
                    {
                        var t = (DateTime.Now - time1).TotalMilliseconds;
                        time1 = DateTime.Now;
                        if (t < 300)
                        {
                            hwindow.ClearWindow();
                            int w, h;
                            image.GetImageSize(out w, out h);
                            hwindow.SetPart(0, 0, h - 1, w - 1);
                            image.DispImage(hwindow);
                        }
                        else
                        {
                            bMouseDown = true;
                            int but;
                            hwindow.GetMposition(out nMouseDownR, out nMouseDownC, out but);
                        }
                    }
                }
                catch (Exception ex)
                {
                    //throw ex;
                    Console.WriteLine(ex.ToString());
                }
            }
            private void hWindowControl1_HMouseMove(object sender, HMouseEventArgs e)
            {
                try
                {
                    if (e.Button == System.Windows.Forms.MouseButtons.Left && bMouseDown)
                    {
                        int row, col, but;
                        hwindow.GetMposition(out row, out col, out but);
                        nMouseMoveEndR = row;
                        nMouseMoveEndC = col;
                        bMouseMoved = true;
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
            private void hWindowControl1_HMouseUp(object sender, HMouseEventArgs e)
            {
                try
                {
                    bMouseDown = false;
                    if (e.Button == System.Windows.Forms.MouseButtons.Left && bMouseMoved)
                    {
                        bMouseMoved = false;
                        int row1, col1, row2, col2;
                        hwindow.GetPart(out row1, out col1, out row2, out col2);
                        int dr = -(int)((nMouseMoveEndR - nMouseDownR) * 1.5);
                        int dc = -(int)((nMouseMoveEndC - nMouseDownC) * 1.5);
                        hwindow.SetPart(row1 + dr, col1 + dc, row2 + dr, col2 + dc);
                        hwindow.ClearWindow();
                        hwindow.DispImage(image);
                    }
                }
                catch (Exception ex) { Console.WriteLine(ex.ToString()); }
            }
            public void EnableZoom()
            {
                try
                {
                    _hWindowControl.HMouseWheel -= hWindowControl_HMouseWheel;
                    _hWindowControl.HMouseDown -= hWindowControl_HMouseDown;
                    _hWindowControl.HMouseUp -= hWindowControl1_HMouseUp;
                    _hWindowControl.HMouseMove -= hWindowControl1_HMouseMove;
                    _hWindowControl.HMouseWheel += hWindowControl_HMouseWheel;
                    _hWindowControl.HMouseDown += hWindowControl_HMouseDown;
                    _hWindowControl.HMouseUp += hWindowControl1_HMouseUp;
                    _hWindowControl.HMouseMove += hWindowControl1_HMouseMove;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
            public void DisableZoom()
            {
                try
                {
                    hWindowControl.HMouseWheel -= hWindowControl_HMouseWheel;
                    hWindowControl.HMouseDown -= hWindowControl_HMouseDown;
                    hWindowControl.HMouseUp -= hWindowControl1_HMouseUp;
                    hWindowControl.HMouseMove -= hWindowControl1_HMouseMove;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                }
            }
        }
    }
    namespace LaserDataProcess_NS
    {
        public class ROILaser
        {
            public double row1;
            public double col1;
            public double row2;
            public double col2;
        }
        public class IfUseModel
        {
            public bool Model1 = false;
            public bool Model2 = false;
        }
        public class LaserDataProcessConfig
        {
            public ROILaser roi1 = new ROILaser();
            public ROILaser roi2 = new ROILaser();
            public IfUseModel IfUseModel = new IfUseModel();
            public int modelCenterDataCount = 10;
            public string Model1FileFullName = "";
            public string Model2FileFullName = "";
        }
        public class LaserDataProcess
        {
            public LaserDataProcessConfig config = new LaserDataProcessConfig();
            public double[] modelData1 { get; set; } = null;
            public double[] modelData2 { get; set; } = null;
            public HWindow hwindow = null;
            public bool Init(LaserDataProcessConfig config, HWindow hwindow = null)
            {
                try
                {
                    this.config = config;
                    this.modelData1 = (from d in File.ReadAllLines(config.Model1FileFullName) select double.Parse(d)).ToArray();
                    this.modelData2 = (from d in File.ReadAllLines(config.Model2FileFullName) select double.Parse(d)).ToArray();
                    this.hwindow = hwindow;
                    return true;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    return false;
                }
            }
            private void GetDataWithModel(double[] srcBuffer, double[] modelData, ROILaser roi, out double[] featureData)
            {
                try
                {
                    double minStandardDeviation;
                    int[] modelPosition;
                    if (modelData == null)
                    {
                        throw (new Exception("模板数据为null"));
                    }
                    FindModel(srcBuffer, modelData, out minStandardDeviation, out modelPosition, (int)roi.col1, (int)roi.col2);
                    featureData = srcBuffer.ToList().GetRange(modelPosition.Sum() / 2 - config.modelCenterDataCount / 2, config.modelCenterDataCount).ToArray();
                    if (hwindow != null)
                    {
                        hwindow.SetColor("red");
                        hwindow.SetDraw("margin");
                        hwindow.DispRectangle1(roi.row1, modelPosition[0], roi.row2, modelPosition[1]);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    throw e;
                }
            }
            private void GetDataWithROI(double[] srcBuffer, ROILaser roi, out double[] roiData)
            {
                try
                {
                    if (roi.col2 - roi.col1 <= 0)
                    {
                        throw (new Exception("roi选择有问题"));
                    }
                    roiData = srcBuffer.ToList().GetRange((int)roi.col1, (int)(roi.col2 - roi.col1) + 1).ToArray();
                    if (hwindow != null)
                    {
                        hwindow.SetColor("red");
                        hwindow.SetDraw("margin");
                        hwindow.DispRectangle1(roi.row1, roi.col1, roi.row2, roi.col2);
                    }
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    throw e;
                }
            }
            public bool ProcessAltitude(double[] srcBuffer, out double altitude)
            {
                altitude = 0;
                try
                {
                    if (hwindow != null)
                    {
                        hwindow.DispRegion(convert(srcBuffer, 4000));
                    }
                    double result = 0;
                    double[] featuredata1, featuredata2;
                    if (config.IfUseModel.Model1)
                    {
                        GetDataWithModel(srcBuffer, modelData1, config.roi1, out featuredata1);
                    }
                    else
                    {
                        GetDataWithROI(srcBuffer, config.roi1, out featuredata1);
                    }
                    if (config.IfUseModel.Model2)
                    {
                        GetDataWithModel(srcBuffer, modelData2, config.roi2, out featuredata2);
                    }
                    else
                    {
                        GetDataWithROI(srcBuffer, config.roi2, out featuredata2);
                    }
                    result = featuredata1.Average() - featuredata2.Average();
                    altitude = result;
                    return true;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    return false;
                }
            }
            private void FindModel(double[] srcBuffer, double[] TemplateData, out double MinStandardDeviation, out int[] ModelPosition, int ROIBegin = -1, int ROIEnd = -1)
            {
                try
                {
                    int begin, end;
                    begin = ROIBegin < 0 ? 0 : ROIBegin;
                    end = ROIEnd < 0 ? srcBuffer.Length - TemplateData.Length : ROIEnd;
                    if (srcBuffer.Length <= TemplateData.Length)
                    {
                        throw new System.Exception("输入数据错误");
                    }
                    double[] offsetBuffer = new double[TemplateData.Length];
                    List<KeyValuePair<int, double>> stdevList = new List<KeyValuePair<int, double>>();
                    for (int i = begin; i <= end; i++)
                    {
                        for (int j = i; j < i + TemplateData.Length; j++)
                        {
                            offsetBuffer[j - i] = TemplateData[j - i] - srcBuffer[j];
                        }
                        //var stdev = (from di in offsetBuffer select di).StandardDeviation();
                        var stdev = offsetBuffer.StandardDeviation();
                        stdevList.Add(new KeyValuePair<int, double>(i, stdev));
                    }
                    stdevList.Sort((d1, d2) => d1.Value.CompareTo(d2.Value));
                    ModelPosition = new int[2] { stdevList[0].Key, stdevList[0].Key + TemplateData.Length - 1 };
                    MinStandardDeviation = stdevList[0].Value;
                }
                catch (System.Exception e)
                {
                    System.Console.WriteLine(e.ToString());
                    throw e;
                }
            }
            public HRegion convert(double[] data, double limitUp)
            {
                try
                {
                    double[] srcData = new double[data.Length];
                    data.CopyTo(srcData, 0);
                    HImage image = new HImage("byte", srcData.Length + 20, (int)(srcData.Max()) + 20);
                    HRegion region = new HRegion();
                    int[] xdata = new int[srcData.Length];
                    double[] ydata = new double[srcData.Length];
                    srcData.CopyTo(ydata, 0);
                    for (int i = 0; i < srcData.Length; i++)
                    {
                        xdata[i] = i;
                    }
                    region.GenRegionPoints(ydata, xdata);
                    return region;
                }
                catch (Exception e)
                {
                    Console.WriteLine(e.ToString());
                    return null;
                }
            }
        }
    }
}
